<?php
//-------------------------------------------------------------------------
// OVIDENTIA http://www.ovidentia.org
// Ovidentia is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2, or (at your option)
// any later version.
// 
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
// USA.
//-------------------------------------------------------------------------
/**
 * @license http://opensource.org/licenses/gpl-license.php GNU General Public License (GPL)
 * @copyright Copyright (c) 2006 by CANTICO ({@link http://www.cantico.fr})
 */
include_once 'base.php';
require_once $GLOBALS['babInstallPath'] . '/addons/widgets/widgets/inputwidget.class.php';
require_once $GLOBALS['babInstallPath'] . '/utilit/dateTime.php';


/**
 * Constructs a Widget_DatePicker.
 *
 * @param string		$id			The item unique id.
 * @return Widget_DatePicker
 */
function Widget_DatePicker($id = null)
{
	return new Widget_DatePicker($id);
}


/**
 * A Widget_DatePicker is a widget that let the user enter a date. 
 */
class Widget_DatePicker extends Widget_InputWidget implements Widget_Displayable_Interface 
{
	/** @var bool $inline  */
	private $inline = false;

	/** @var bool $selectableYear  */
	private $selectableYear;

	/** @var bool $selectableMonth  */
	private $selectableMonth;
	
	/** @var BAB_DateTime $mindate  */
	private $mindate;

	/** @var BAB_DateTime $maxdate  */
	private $maxdate;
	
	/** @var int $numberOfMonths  */
	private $numberOfMonths = array(1, 1);
	
	/** @var string $dateClickUrl  */
	private $dateClickUrl = '';
	
	/** @var int $size  */
	private $size = 10;
	
	/**
	 * @param string $id			The item unique id.
	 * @return Widget_DatePicker
	 */
	public function __construct($id = null)
	{
		parent::__construct($id);
		$this->setFormat('%d-%m-%Y');
	}


	/**
	 * Sets the format of the date.
	 * Only usage of %d, %m, %Y are allowed
	 *
	 * @param string $format	The format string as described in the php strftime function.
	 * @return Widget_DatePicker
	 */
	public function setFormat($format)
	{
		assert('is_string($format); /* The "format" parameter must be a string */');
		$this->setMetadata('format', $format);
		return $this;
	}

	/**
	 * Returns the format of the date.
	 *
	 * @return string
	 */
	public function getFormat()
	{
		return $this->getMetadata('format');
	}


	/**
	 * @return string ISO date or empty string
	 */
	public function getValue() {
	
		$value = parent::getValue();
		if ('' === $value) {
			return '';
		}
			
		if (!preg_match('/\d{4}-\d\d-\d\d/', $value)) {
			if (false === $value = $this->getISODate($value)) {
				return '';
			}
		}
		
		assert('preg_match(\'/\d{4}-\d\d-\d\d/\', $value); /* The "value" must be an ISO date or empty string, not (' . $value . ') */');
		return $value;
	}


	public function getClasses()
	{
		$classes = parent::getClasses();
		if(!$this->isDisplayMode()){
			$classes[] = 'widget-datepicker';
		}
		return $classes;
	}


	/**
	 * Activates or deactivates the possibility for the user to choose the
	 * year from a drop down list.
	 * 
	 * @param bool $active
	 * @return Widget_DatePicker
	 */
	public function setSelectableYear($active = true) {
		$this->selectableYear = $active;
		return $this;
	}

	/**
	 * Returns true if the user has the possibility to choose the
	 * year from a drop down list.
	 * 
	 * @return bool
	 */
	public function getSelectableYear() {
		return $this->selectableYear;
	}


	/**
	 * Specify a date minimum which the date can't be before
	 * 
	 * @param BAB_DateTime $date
	 * @return Widget_DatePicker
	 */
	public function setMinDate(BAB_DateTime $date) {
		$this->mindate = $date;
		return $this;
	}
	
	/**
	 * Return the minimum date "BAB_DateTime" object
	 * 
	 * @return BAB_DateTime
	 */
	public function getMinDate() {
		return $this->mindate;
	}


	/**
	 * Specify a date maximum which the date can't be before
	 * 
	 * @param BAB_DateTime $date
	 * @return Widget_DatePicker
	 */
	public function setMaxDate(BAB_DateTime $date) {
		$this->maxdate = $date;
		return $this;
	}
	
	/**
	 * Return the maximum date "BAB_DateTime" object
	 * 
	 * @return BAB_DateTime
	 */
	public function getMaxDate() {
		return $this->maxdate;
	}

	
	/**
	 * Selects if the date picker should appear as a dropdown or inline.
	 * 
	 * @param bool $active
	 * @return Widget_DatePicker
	 */
	public function setInline($active = true) {
		$this->inline = $active;
		return $this;
	}

	/**
	 * Returns true if the date picker is set to appear inline.
	 * 
	 * @return bool
	 */
	public function getInline() {
		return $this->inline;
	}

	/**
	 * Activates or deactivates the possibility for the user to choose the
	 * month from a drop down list.
	 * 
	 * @param bool $active
	 * @return Widget_DatePicker
	 */
	public function setSelectableMonth($active = true) {
		$this->selectableMonth = $active;
		return $this;
	}

	/**
	 * Returns true if the user has the possibility to choose the
	 * month from a drop down list.
	 * 
	 * @return bool
	 */
	public function getSelectableMonth() {
		return $this->selectableMonth;
	}

	/**
	 * Change the size of the date picker input field (in characters) when not inline.
	 * 
	 * @param int $size
	 * @return Widget_DatePicker
	 */
	public function setSize($size) {
		$this->size = $size;
		return $this;
	}

	/**
	 * Returns the size of the date picker input field (in characters) when not inline.
	 * 
	 * @return int
	 */
	public function getSize() {
		return $this->size;
	}

	
	/**
	 * Change the number of months displayed by the date picker
	 * 
	 * @param int $numberOfMonths
	 * @return Widget_DatePicker
	 */
	public function setNumberOfMonths($numberOfMonthsHorizontal, $numberOfMonthsVertical = 1) {
		$this->numberOfMonths = array($numberOfMonthsVertical, $numberOfMonthsHorizontal);
		return $this;
	}

	/**
	 * Returns the number of months displayed by the date picker
	 * 
	 * @return int
	 */
	public function getNumberOfMonths() {
		return $this->numberOfMonths;
	}



	/**
	 * Sets
	 * @param string	$url
	 * @return Widget_DatePicker
	 */
	public function setDateClickUrl($url)
	{
		$this->dateClickUrl = $url;
		return $this;
	}

	/**
	 * Returns 
	 * 
	 * @return string
	 */
	public function getDateClickUrl()
	{
		return $this->dateClickUrl;
	}



	/**
	 * get title of widget (tooltip)
	 * @return string
	 */
	public function getTitle()
	{
		$title = parent::getTitle();
		if (!isset($title)) {
			$dateFormat = str_replace(array('%d', '%m', '%Y'), array('jj', 'mm', 'aaaa'), $this->getFormat());
			$dateExample = strftime($this->getFormat(), bab_mktime('2005-12-25'));
			return sprintf(widget_translate("Date format: '%s'.  Eg. '%s'"), $dateFormat, $dateExample);
		}
		return $title; 
	}
	
	
	/**
	 * get ISO from a date typed in the format set in the setFormat method
	 * @param	string	$date
	 * @return 	string|false	ISO date or false if error
	 */
	public function getISODate($date) 
	{
		if (empty($date)) {
			return '0000-00-00';
		}

		$expreg = str_replace(
			array('%d', '%m', '%Y'),
			/**
			 * We use the ?P<name> (named subpattern) notation which is compatible with
			 * pre-5.2.2 versions of PHP and seems to also work with more recent versions.
			 * @see http://php.net/preg_match => "Using named subpattern" 
			 */
			array('(?P<day>[0-9]{1,2})', '(?P<month>[0-9]{1,2})', '(?P<year>[0-9]{4})'),
			'/'.preg_quote($this->getFormat(), '/').'/'
		);
		
		if (preg_match($expreg, $date, $regs)) {
			return sprintf('%04d-%02d-%02d',$regs['year'],$regs['month'],$regs['day']);
		} else {
			return false;
		}
	
	}
	
	


	public function display(Widget_Canvas $canvas)
	{	
		$value = $this->getValue();
		if (empty($value) || $value == '0000-00-00') {
			$value = '';
		} else {
			$value = strftime($this->getFormat(), bab_mktime($this->getValue()));
		}

		if ($this->getSelectableMonth()) {
			$this->addClass('widget-datepicker-changemonth');
		}
		if ($this->getSelectableYear()) {
			$this->addClass('widget-datepicker-changeyear');
		}
		if ($this->isDisplayMode()) {

			$classes = $this->getClasses();
			$classes[] = 'widget-displaymode';

			return $canvas->richtext(
					$this->getId(), 
					$classes, 
					$value, 
					BAB_HTML_ALL ^ BAB_HTML_P,
					$this->getCanvasOptions()
			);

		}
		
		$this->setMetadata('numberOfMonths', $this->numberOfMonths);
		$this->setMetadata('dateClickUrl', $this->dateClickUrl);
		
		if ($this->getMinDate() != null){
			$this->setMetadata('mindatey', $this->getMinDate()->getYear() );
			$this->setMetadata('mindatem', $this->getMinDate()->getMonth() );
			$this->setMetadata('mindated', $this->getMinDate()->getDayOfMonth() );
		}
		
		if ($this->getMaxDate() != null){
			$this->setMetadata('maxdatey', $this->getMaxDate()->getYear() );
			$this->setMetadata('maxdatem', $this->getMaxDate()->getMonth() );
			$this->setMetadata('maxdated', $this->getMaxDate()->getDayOfMonth() );
		}
		
		if ($this->getInline()) {
			$datePicker = $canvas->div(
									$this->getId(),
									$this->getClasses(),
									array($this->getValue())
								);
		} else {
			$datePicker = $canvas->lineInput(
									$this->getId(),
									$this->getClasses(),
									$this->getFullName(),
									$value,
									$this->getSize(),
									10,
									$this->isDisabled(),
									$this->getTitle()
								);
		}
		return $datePicker . $canvas->metadata($this->getId(), $this->getMetadata());
	}

}
